#include "vroute_task.hpp"
#include "vrouteErrors.hpp"
#include "logger.hpp"
#include "vroute_stack.hpp"
#include "vroute_IJob.hpp"

namespace vroute_stack
{
    CTaskMgr* CTaskMgr::_instance = nullptr;
    CTaskMgr* CTaskMgr::getInstance()
    {
        if(nullptr == _instance)
        {
            _instance = new CTaskMgr();
        }
        return _instance;
    }

    void  CTaskMgr::releaseInstance()
    {
        if (nullptr != _instance)
        {
            delete _instance;
            _instance = nullptr;
        }     
    }

    int CTaskMgr::init(SystemStartType type)
    {
        m_working = 1;
        return e_vroute_sucess;
    }

    CTaskMgr::CTaskMgr()
    {
        m_job_ms_500 = (IJob**)calloc(max_task_term_count, sizeof(IJob**));
        m_job_count_ms_500 = 0;
        m_job_sec_1 = (IJob**)calloc(max_task_term_count, sizeof(IJob**));
        m_job_count_sec_1 = 0;
        m_job_sec_5 = (IJob**)calloc(max_task_term_count, sizeof(IJob**));
        m_job_count_sec_5 = 0;
        m_job_sec_30 = (IJob**)calloc(max_task_term_count, sizeof(IJob**));
        m_job_count_sec_30 = 0;
        m_job_min_1 = (IJob**)calloc(max_task_term_count, sizeof(IJob**));
        m_job_count_min_1 = 0;
        vos_InitCriticalSection(&m_cs_task);
        m_working = 0;
    }

    CTaskMgr::~CTaskMgr()
    {
        m_working = 0;
        freeInsMaic(m_job_ms_500)
        freeInsMaic(m_job_sec_1)
        freeInsMaic(m_job_sec_5)
        freeInsMaic(m_job_sec_30)
        freeInsMaic(m_job_min_1)
        vos_destroy_CriticalSection(&m_cs_task);
    }

    unsigned int CTaskMgr::registTask(IJob* job, taskTimerTime type)
    {
        IJob** tempArr = nullptr;
        int* count = nullptr; 
        int index = 0;
        int ret = 0;
        vos_EnterCriticalSection(&m_cs_task);
        switch (type)
        {
        case task_timer_ms_500:
            tempArr = m_job_ms_500;
            count = &m_job_count_ms_500;
            ret = 0x0100;
            break;
        case task_timer_sec_1:
            tempArr = m_job_sec_1;
            count = &m_job_count_sec_1;
            ret = 0x0200;
            break;
        case task_timer_sec_5:
            tempArr = m_job_sec_5;
            count = &m_job_count_sec_5;
            ret = 0x0300;
            break;
        case task_timer_sec_30:
            tempArr = m_job_sec_30;
            count = &m_job_count_sec_30;
            ret = 0x0400;
            break;
        case task_timer_min_1:
            tempArr = m_job_min_1;
            count = &m_job_count_min_1;
            ret = 0x0500;
            break;
        default:
            break;
        }
        for(; index < max_task_term_count; ++index)
        {
            if (tempArr[index] == nullptr)
            {
                tempArr[index] = job;
                *count = *count + 1;
            }
        }
        vos_LeaveCriticalSection(&m_cs_task);
        if (index == max_task_term_count)
        {
            return -1;
        }
        ret |= index;
        return ret;
    }

    int CTaskMgr::removeTask(unsigned int taskId)
    {
        int type = taskId & 0x0000FF00;
        int index = taskId & 0x000000FF;
        if (type > 5 || index > max_task_term_count)
        {
            return e_vroute_parasError;
        }

        switch (type)
        {
        case 1:
            m_job_ms_500[index] = nullptr;
            --m_job_count_ms_500;
            return e_vroute_sucess;
        case 2:
            m_job_sec_1[index] = nullptr;
            --m_job_count_sec_1;
            return e_vroute_sucess;
        case 3:
            m_job_sec_5[index] = nullptr;
            --m_job_count_sec_5;
            return e_vroute_sucess;
        case 4:
            m_job_sec_30[index] = nullptr;
            --m_job_count_sec_30;
            return e_vroute_sucess;
        case 5:
            m_job_min_1[index] = nullptr;
            --m_job_count_min_1;
            return e_vroute_sucess;
        default:
            return e_vroute_parasError;
        }
    }

    vos_threadRetType CTaskMgr::run_ms_500(void* p)
    {
        CTaskMgr* ins = (CTaskMgr*)p;
        return ins->run_ms_500_ins();
    }

    vos_threadRetType CTaskMgr::run_sec_1(void* p)
    {
        CTaskMgr* ins = (CTaskMgr*)p;
        return ins->run_sec_1_ins();
    }

    vos_threadRetType CTaskMgr::run_sec_5(void* p)
    {
        CTaskMgr* ins = (CTaskMgr*)p;
        return ins->run_sec_5_ins();
    }

    vos_threadRetType CTaskMgr::run_sec_30(void* p)
    {
        CTaskMgr* ins = (CTaskMgr*)p;
        return ins->run_sec_30_ins();
    }

    vos_threadRetType CTaskMgr::run_min_1(void* p)
    {
        CTaskMgr* ins = (CTaskMgr*)p;
        return ins->run_min_1_ins();
    }

    vos_threadRetType CTaskMgr::run_ms_500_ins()
    {
        int index = 0;
        while (m_working)
        {
            for (; m_working && m_job_count_ms_500 && m_job_ms_500[index] != nullptr; ++index)
            {
                m_job_ms_500[index]->CEntry1(nullptr);
            }
            vos_sleep(500);
        }
        return vos_threadRetValue;
    }

    vos_threadRetType CTaskMgr::run_sec_1_ins()
    {
        int index = 0;
        while (m_working)
        {
            for (; m_working && m_job_count_sec_1 && m_job_sec_1[index] != nullptr; ++index)
            {
                m_job_sec_1[index]->CEntry1(nullptr);
            }
            vos_sleep_sec(1);
        }
        return vos_threadRetValue;
    }

    vos_threadRetType CTaskMgr::run_sec_5_ins()
    {
        int index = 0;
        while (m_working)
        {
            for (; m_working && m_job_count_sec_5 && m_job_sec_5[index] != nullptr; ++index)
            {
                m_job_sec_5[index]->CEntry1(nullptr);
            }
            vos_sleep_sec(5);
        }
        return vos_threadRetValue;
    }

    vos_threadRetType CTaskMgr::run_sec_30_ins()
    {
        int index = 0;
        while (m_working)
        {
            for (; m_working && m_job_count_sec_30 && m_job_sec_30[index] != nullptr; ++index)
            {
                m_job_sec_30[index]->CEntry1(nullptr);
            }
            vos_sleep_sec(30);
        }
        return vos_threadRetValue;
    }

    vos_threadRetType CTaskMgr::run_min_1_ins()
    {
        int index = 0;
        while (m_working)
        {
            for (; m_working && m_job_count_min_1 && m_job_min_1[index] != nullptr; ++index)
            {
                m_job_min_1[index]->CEntry1(nullptr);
            }
            vos_sleep(60);
        }
        return vos_threadRetValue;
    }
}